home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / dev / misc / FetchRefs1.3.lha / FetchRefs1.3 / Source.lha / Source / FetchRefs / MessageLoop.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-07-04  |  8.3 KB  |  312 lines

  1. /* MessageLoop.c
  2. Originaly written by Anders Melchiorsen, modified by Roland Florac
  3. Handles the messages received by FetchRefs (Commodities, ARexx, Break)
  4. Modified from the original version for the ARexx interface */
  5.  
  6. #include "FetchRefs.h"
  7. #include <proto/rexxsyslib.h>
  8.  
  9. static void __regargs traiter_message_ARexx (struct RexxMsg * message);
  10.  
  11. struct Library *CxBase;
  12. struct MsgPort *CxPort, * rexxPort;
  13. CxObj *FRBroker;
  14.  
  15. char *RexxHostName;
  16.  
  17. /* Give each of the ARexx commands we can receive an ID. FR_DUMMY is for
  18.  * illegal commands; read more below... */
  19. enum ARexxID { FR_DUMMY, FR_QUIT, FR_GET, FR_CLEAR, FR_NEW, FR_ADD };
  20.  
  21. /* MessageLoop() - main loop waits for Cx, ARexx, or ^C */
  22. void MessageLoop (void)
  23. {
  24.     /* Main loop - process ARexx commands until we receive a ^C signal */
  25.     for(;;)
  26.     {
  27.     LONG mask;
  28.  
  29.     mask = Wait (SIGBREAKF_CTRL_C | (1 << rexxPort->mp_SigBit) | (1 << CxPort->mp_SigBit));
  30.  
  31.     /* FR_QUIT will signal FindTask(NULL) with ^C. Naturally, a ^C may
  32.      * also be sent by external means like C:Break or anything else.
  33.      */
  34.     if (mask & SIGBREAKF_CTRL_C)
  35.         return;
  36.  
  37.     /* We received an ARexx message. We use the DICE interface to process
  38.      * it. ProcessRexxCommands() will in turn call the DoRexxCommand()
  39.      * below.
  40.      */
  41.     if (mask & (1 << rexxPort->mp_SigBit))
  42.     {   struct RexxMsg * message;
  43.         while (message = (struct RexxMsg *) GetMsg (rexxPort))
  44.         traiter_message_ARexx (message);
  45.     }
  46.  
  47.     /* Handle Commodities message */
  48.     if (mask & (1 << CxPort->mp_SigBit))
  49.         HandleCxMessage ();
  50.     }
  51. }
  52.  
  53. /* The theory of parsing the messages is based on a two pass ReadArgs() parsing.
  54.  *
  55.  * First the entire message is parsed against RexxArgStr, and as all commands
  56.  * are postfixed by /F the entire rest of the line is considered to be the
  57.  * parameter of this single command. If an unrecognised keyword is entered then
  58.  * everything is considered a parameter to DUMMY (as it's the first one); thus
  59.  * out-of-context commands are flushed out here.
  60.  *
  61.  * Having had ReadArgs() put everything but the command name into a string, we
  62.  * can parse this against a template which differs for each command, but as all
  63.  * the templates are in an array we simply need one ReadArgs() call along with
  64.  * the right offset into this array (which is determined by what the command
  65.  * was). After having parsed again (but only if it's a succes), a switch can
  66.  * decide what actions should be made with the parameters parsed last - which
  67.  * depends on what the first parsing resulted in.
  68.  *
  69.  * As clear as mud, right? Anyway, I like it :-).
  70.  *
  71.  * (And later I learned about ARexxBox... :-).
  72.  */
  73.  
  74. /* Templates used by ARexx interface */
  75. UBYTE RexxArgStr[] = "FR_DUMMY/F,FR_QUIT/F,FR_GET/F,FR_CLEAR/F,FR_NEW/F,FR_ADD/F";
  76.  
  77. STRPTR RexxTemplates[] = {
  78. /* FR_DUMMY */    NULL,
  79. /* FR_QUIT  */    NULL,
  80. /* FR_GET   */    "FIND/A,TO/A,PUBSCREEN,FILEREF/S,CASE/S",
  81. /* FR_CLEAR */    NULL,
  82. /* FR_NEW   */    "FILE/M",
  83. /* FR_ADD   */    "FILE/M"
  84. };
  85.  
  86. /* The following routine is called everytime we receive an ARexx msg.
  87.  * Depending on what the message was, different actions are performed.
  88.  */
  89. static __regargs LONG DoRexxCommande (void *msg, char *arg0)
  90. {
  91.     struct FindRefReturnStruct RetCode = { RET_OKAY, 0 };
  92.     UBYTE str[256];
  93.  
  94.     struct RDArgs *RexxArgs, *ArgsArgs;
  95.     STRPTR RexxResult[sizeof(RexxTemplates) / sizeof(RexxTemplates[0])];
  96.     STRPTR ArgsResult[10];
  97.  
  98.     /* Flush out garbage as ReadArgs() allows for pre-initialized values */
  99.     setmem (RexxResult, sizeof(RexxResult), 0);
  100.     setmem (ArgsResult, sizeof(ArgsResult), 0);
  101.  
  102.     /* ReadArgs() needs a '\n' at the end of its strings :-( */
  103.     strcpy (str, arg0);
  104.     strcat (str, "\n");
  105.  
  106.     if ((RexxArgs = AllocDosObject (DOS_RDARGS, NULL)) && (ArgsArgs = AllocDosObject (DOS_RDARGS, NULL)))
  107.     {
  108.     RexxArgs->RDA_Source.CS_Buffer = str;
  109.     RexxArgs->RDA_Source.CS_Length = strlen(str);
  110.     RexxArgs->RDA_Flags = RDAF_NOPROMPT;
  111.     if (ReadArgs (RexxArgStr, (LONG *) RexxResult, RexxArgs))
  112.     {
  113.         LONG argno;
  114.  
  115.         /* Figure out which command we got */
  116.         for (argno = 0;  ! RexxResult[argno];  argno++);
  117.  
  118.         /* If a template is specified: parse the arguments */
  119.         if (RexxTemplates[argno])
  120.         {
  121.         /* We still have to add '\n' to the string due to ReadArgs() */
  122.         strcpy (str, RexxResult[argno]);
  123.         strcat (str, "\n");
  124.  
  125.         /* Now parse the arguments to whatever the command is */
  126.         ArgsArgs->RDA_Source.CS_Buffer = str;
  127.         ArgsArgs->RDA_Source.CS_Length = strlen(str);
  128.         ArgsArgs->RDA_Flags = RDAF_NOPROMPT;
  129.         if (!(ReadArgs (RexxTemplates[argno], (LONG *)ArgsResult, ArgsArgs)))
  130.         {
  131.             RetCode.Result = RET_FAULT;
  132.             RetCode.Number = IoErr();
  133.         }
  134.         }
  135.  
  136.         /* If ReadArgs() failed the return code is changed (above) and
  137.          * therefore the switch() will only be executed if everything
  138.          * is allright so far.
  139.          */
  140.         if (RetCode.Result == RET_OKAY)
  141.         switch (argno)
  142.         {
  143.             case FR_DUMMY:
  144.             RetCode.Result = RET_FAULT;
  145.             RetCode.Number = ERROR_REQUIRED_ARG_MISSING;
  146.             break;
  147.  
  148.             case FR_QUIT:
  149.             Signal (FindTask(NULL), SIGBREAKF_CTRL_C);
  150.             break;
  151.  
  152.             case FR_GET:
  153.             {
  154.             struct FindRefOptions FindOpts;
  155.             FindOpts.Reference     = ArgsResult[0];
  156.             FindOpts.DestFile      = ArgsResult[1];
  157.             FindOpts.PubScreen     = ArgsResult[2];
  158.             FindOpts.FileRef       = (BOOL) ArgsResult[3];
  159.             FindOpts.Case           = (BOOL) ArgsResult[4];
  160.  
  161.             FindRef (&FindOpts, &RetCode);
  162.             }
  163.             break;
  164.  
  165.             case FR_CLEAR:
  166.             FreeRefs();
  167.             break;
  168.  
  169.             case FR_NEW:
  170.             FreeRefs();
  171.  
  172.             /* FR_NEW falls through to FR_ADD. Naturally this requires
  173.              * them to have the same templates. */
  174.  
  175.             case FR_ADD:
  176.             ReadWild ((STRPTR (*)[]) ArgsResult[0]);
  177.             break;
  178.         }
  179.     }
  180.     else
  181.     {
  182.         RetCode.Result = RET_FAULT;
  183.         RetCode.Number = IoErr();
  184.     }
  185.  
  186.     FreeArgs (ArgsArgs);
  187.     FreeDosObject (DOS_RDARGS, ArgsArgs);
  188.     }
  189.     else
  190.     {
  191.     RetCode.Result = RET_FAULT;
  192.     RetCode.Number = ERROR_NO_FREE_STORE;
  193.     }
  194.  
  195.     if (RexxArgs)
  196.     {
  197.     FreeArgs (RexxArgs);
  198.     FreeDosObject (DOS_RDARGS, RexxArgs);
  199.     }
  200.  
  201.     /* Find out what the secondary (RC2) return code should be. This is,
  202.      * of course, dependent on the primary (RC) return code.
  203.      */
  204.     switch (RetCode.Result)
  205.     {
  206.     case RET_MATCH:
  207.         SPrintf (str, "%ld", RetCode.Number);
  208.     break;
  209.  
  210.     case RET_NO_MATCH:
  211.         strcpy (str, GetString (TEXTE_NOREF));
  212.     break;
  213.  
  214.     case RET_ABORT:
  215.         strcpy (str, GetString (TEXTE_ABORT));
  216.     break;
  217.  
  218.     case RET_FAULT:
  219.         Fault (RetCode.Number, "FetchRefs", str, 256);
  220.     break;
  221.     }
  222.     SetRexxVar (msg, "RC2", str, strlen(str));
  223.  
  224.     /* Set the return code (RC) to 0, 5, 10 or 20 */
  225.     if ((RetCode.Result == RET_OKAY) || (RetCode.Result == RET_MATCH))
  226.     return RETURN_OK;
  227.     else if (RetCode.Result == RET_ABORT)
  228.     return RETURN_WARN;
  229.     else if (RetCode.Result == RET_NO_MATCH)
  230.     return RETURN_ERROR;
  231.     else
  232.     return RETURN_FAIL;
  233. }
  234.  
  235. static void __regargs traiter_message_ARexx (struct RexxMsg * message)
  236. {   if (message->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)    /* really usefull ? */
  237.     {    DeleteArgstring (message->rm_Args[0]);
  238.     DeleteRexxMsg (message);
  239.     return;
  240.     }
  241.     message->rm_Result2 = 0;
  242.     message->rm_Result1 = DoRexxCommande (message, message->rm_Args[0]);
  243.     ReplyMsg ((struct Message *) message);
  244. }
  245.  
  246. /* HandleCxMessage() - take care of any Cx message */
  247. void HandleCxMessage (void)
  248. {
  249.     CxMsg *msg;
  250.  
  251.     while (msg = (CxMsg *) GetMsg (CxPort))
  252.     {
  253.     ULONG msg_id = CxMsgID(msg), msg_type = CxMsgType(msg);
  254.  
  255.     ReplyMsg ((struct Message *) msg);
  256.  
  257.     if (msg_type == CXM_COMMAND)
  258.         switch (msg_id)
  259.         {
  260.         case CXCMD_DISABLE:
  261.             ActivateCxObj (FRBroker, FALSE);
  262.         break;
  263.  
  264.         case CXCMD_ENABLE:
  265.             ActivateCxObj (FRBroker, TRUE);
  266.         break;
  267.  
  268.         case CXCMD_KILL:
  269.             Signal (FindTask (NULL), SIGBREAKF_CTRL_C);
  270.         break;
  271.         }
  272.     }
  273. }
  274.  
  275.  
  276. /* InstallCx() - set up the Commodities Broker */
  277. void InstallCx (STRPTR name)
  278. {   static struct NewBroker fr_broker =
  279.     {
  280.     NB_VERSION,
  281.     NULL,
  282.     0,
  283.     0,
  284.     NULL,
  285.     NULL,
  286.     0, NULL, 0
  287.     };
  288.  
  289.     fr_broker.nb_Descr = GetString (TEXTE_RECHERCHE);
  290.     fr_broker.nb_Title = GetString (TEXTE_VERSION);
  291.  
  292.     if (CxBase = OpenLibrary ("commodities.library", 37))
  293.     {
  294.     if (CxPort = CreateMsgPort())
  295.     {
  296.         fr_broker.nb_Name = name;
  297.         fr_broker.nb_Port = CxPort;
  298.  
  299.         if (FRBroker = CxBroker (&fr_broker, NULL))
  300.         ActivateCxObj (FRBroker, TRUE);
  301.     }
  302.     }
  303. }
  304.  
  305. /* RemoveCx() - remove the Commodities Broker if it was set up */
  306. void RemoveCx (void)
  307. {   if (FRBroker)
  308.     DeleteCxObjAll (FRBroker);
  309.     DeleteMsgPort (CxPort);
  310.     CloseLibrary (CxBase);
  311. }
  312.